﻿using System;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
using DataTable = System.Data.DataTable;

namespace SwimmingCompetitions
{
    class TablePublisher : IDisposable
    {
        private const int TitleMargin = 2;

        private readonly string _title;
        private readonly DataTable _table;
        private readonly ColumnState[] _columns;

        private Workbook _workbook;
        private Worksheet _worksheet;
        private Application _app;

        public TablePublisher(DataTable table, string title, ColumnState[] columns)
        {
            _title = title;
            _table = table;
            _columns = columns;
        }

        private void printPreview()
        {
            dynamic wbs = null;
            try
            {
                _app = new Application();
                _app.Visible = true;
                _app.DisplayAlerts = false;
                wbs = _app.Workbooks;
                _workbook = wbs.Add(1);
                _worksheet = (Worksheet)_workbook.Sheets[1];
                var col = 0;
                for (var i = 0; i < _table.Columns.Count; ++i)
                {
                    if (_columns[i] != ColumnState.Hidden)
                    {
                        _worksheet.Cells[TitleMargin + 1, col + 1] = _table.Columns[i].ColumnName;
                        _worksheet.Cells[TitleMargin + 1, col + 1].Borders.LineStyle = XlLineStyle.xlContinuous;
                        col++;
                    }
                }
                for (var i = 0; i < _table.Rows.Count; ++i)
                {
                    col = 0;
                    for (var j = 0; j < _table.Columns.Count; ++j)
                    {
                        if (_columns[j] != ColumnState.Hidden)
                        {
                            _worksheet.Cells[TitleMargin + i + 1 + 1, col + 1] = _table.Rows[i][j].ToString();
                            _worksheet.Cells[TitleMargin + i + 1 + 1, col + 1].Borders.LineStyle =
                                XlLineStyle.xlContinuous;
                            col++;
                        }
                    }
                }
                var range = _worksheet.Range["A1", "Z" + (_table.Rows.Count + 1)];
                range.Columns.AutoFit();
                _worksheet.Cells[1, 1] = _title;//after fitting not to affect by long text
                _workbook.PrintPreview(false);
                //_workbook.Save();
            }
            finally
            {
                try
                {
                    _app.Quit();
                    _app = null;
                }
                catch (Exception ex)
                {
                    Logger.Instance.Log("Failed to quit Excel application", ex);
                }
                releaseObject(wbs);
                releaseObject(_worksheet);
                releaseObject(_workbook);
                releaseObject(_app);
            }
        }

        public void PrintPreview()
        {
            printPreview();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        private static void releaseObject(object obj)
        {
            if (obj == null) return;
            try
            {
                while (Marshal.ReleaseComObject(obj) > 0) ;
            }
            catch (Exception ex)
            {
                Logger.Instance.Log("Failed to release COM object", ex);
            }
        }

        public void Dispose()
        {
            if (_app != null)
            {
                try
                {
                    _app.Quit();
                }
                catch (Exception ex)
                {
                    Logger.Instance.Log("Failed to quit Excel application", ex);
                }
            }
            releaseObject(_worksheet);
            releaseObject(_workbook);
            releaseObject(_app);
        }
    }
}
